<template>
  <div :class="['control_box', isFixed && 'fixed']">
    <div v-if="isFixed" class="flex_b_c music_info">
      <div class="flex_a_c">
        <img class="cover_img" :src="musicList[musicIndex].cover_image_url" alt="">
        {{ musicList[musicIndex].song_name }}
      </div>
      <div class="flex_a_c">
        <img class="music_opt" @click="onGiveLike" src="../assets/img/music/givelike_mask_icon.png" alt="">
        <img class="music_opt" src="../assets/img/music/share_mask_icon.png" alt="">
      </div>
    </div>
    <div class="control flex_a_c" @click.stop>
      <!-- 只有一首音乐 不可点击前进后退 -->
      <img v-if="musicList.length === 1" src="../assets/img/music/prev_disabled_icon.png" alt="" class="opt_icon">
      <img v-else @click="onChangeMusic(-1)" src="../assets/img/music/prev_control_icon.png" alt="" class="opt_icon">
      <!-- 播放暂停 -->
      <img v-if="isPlay" @click="playtOrPauseAudio" src="../assets/img/music/pause_icon.png" alt="" class="opt_center_icon">
      <img v-else @click="playtOrPauseAudio" src="../assets/img/music/play_icon.png" alt="" class="opt_center_icon">
      <!-- 只有一首音乐 不可点击前进后退 -->
      <img v-if="musicList.length === 1" src="../assets/img/music/next_disabled_icon.png" alt="" class="opt_icon">
      <img v-else @click="onChangeMusic" src="../assets/img/music/next_control_icon.png" alt="" class="opt_icon">
      <div class="progress pt-3 mr-16"
        @touchstart.capture="handleTouchStart"
        @touchmove.capture="handleTouchMove"
        @touchend.capture="handleTouchEnd">
        <div ref="progress" class="progress_bar" >
          <div class="progress_bar_inner" :style="{width: progressBar + '%'}">
            <span :class="[isScale && 'scale_circle']" ></span>
          </div>
        </div>
        <div class="flex_b_c mt-7">
          <p>{{ convertSecondsToMMSS(currentTime) }}</p>
          <p>{{ convertSecondsToMMSS(duration) }}</p>
        </div>
      </div>
      <img v-show="playType === 3" @click="onChangePlayType(1)" src="../assets/img/music/random_icon.png" alt="" class="opt_icon">
      <img v-show="playType === 2" @click="onChangePlayType(3)"  src="../assets/img/music/single_icon.png" alt="" class="opt_icon">
      <img v-show="playType === 1" @click="onChangePlayType(2)"  src="../assets/img/music/loop_icon.png" alt="" class="opt_icon">
    </div>
  </div>
</template>
<script setup>
import { showLoadingToast, showToast, closeToast  } from 'vant'
import { nextTick, ref, watch, onBeforeUnmount, computed } from 'vue'
import { useMusicStore } from '@/store/index';
import { storeToRefs } from "pinia";
import { useRoute, useRouter } from "vue-router";
import { postGiveLike } from '@/api'
let route = useRoute()
let router = useRouter()
const store = useMusicStore();
const { musicIndex, musicList, isPlay, changePlayStatus } = storeToRefs(store)
let playType = ref(1) //1 列表循环 2 单曲循环 3 随机播放
var ctx = new (AudioContext || webkitAudioContext())();
let source = null; // 创建音频源头节点
let duration = ref(0) // 音频信息
let currentTime = ref(0);
let progressBar = ref(0)
let timer = ref(null)
let diffTime = ref(0)
let onGiveLike = async () => {
  const { code, data } = await postGiveLike({ song_id: musicList.value[musicIndex.value].id })
  if (code === 200) {
    showToast('点赞成功')
    ++musicList.value[musicIndex.value].like_count
  }
}
onBeforeUnmount(() => {
  console.log('清除beforeUnmounted')
  window.clearTimeout(timer.value)
  clearAudio()
})
// 播放
const initPlayAudio = async isShowLoading =>  {
  if (!source) {
    source = ctx.createBufferSource()
    const audioBuffer = await loadAudio(isShowLoading);
    duration.value = audioBuffer.duration
    playSound(audioBuffer);
  }
}
let isFixed = computed(() => {
  let hasArr = ['musicCenter', 'music']
  return hasArr.includes(route.name)
})

watch(musicIndex, (n, oldVal) => {
  if (n !== oldVal) {
    if (isPlay.value) {
      clearAudio()
    }
    initPlayAudio(true)
  }
}, { immediate: true })
watch(changePlayStatus, (n, oldVal) => {
  if (n !== oldVal) {
    playtOrPauseAudio()
  }
})
// 切换播放方式
let onChangePlayType = type => {
  playType.value = type
  let title = {
    1: '列表循环',
    2: '单曲循环',
    3: '随机播放'
  }[type]
  // 设置单曲播放
  // source.loop = type === 2 ? true : false
  showToast(title)
}

// 暂停、继续播放
async function playtOrPauseAudio() {
  if (!source) {
    initPlayAudio(true)
    return false
  };
  if (ctx.state === "running") {
    // 暂停播放
    window.clearTimeout(timer.value)
    ctx.suspend();
    store.setPlayStatus(false)
  } else if (ctx.state === "suspended") {
    // 继续播放
    console.log('继续播放', ctx, source)
    updateProgress()
    ctx.resume();
    store.setPlayStatus(true)

  }
}

// 时长转为分秒
function convertSecondsToMMSS(seconds) {
    var minutes = Math.floor(seconds / 60);
    var seconds = Math.floor(seconds % 60);
    return minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
}
// 进度条
function updateProgress() {
  // console.log('更新进度了', source , diffTime.value)
  window.clearTimeout(timer.value)
  if (source) {
    currentTime.value = source.context.currentTime + diffTime.value;
    progressBar.value = (currentTime.value / duration.value) * 100;
    timer.value = window.setTimeout(updateProgress, 100);
  }
}
// 拖拽进度条
let progress = ref('') // 进度条父元素的宽度
let isScale = ref(false)
let startX = ref('')
let _progressBar // 保存初始化进度条的比例
function handleTouchStart(event) {
  isScale.value = true
  startX.value = event.touches[0].clientX;
  _progressBar = progressBar.value
  window.clearTimeout(timer.value)
  
}
function handleTouchMove(event) {
  const currentX = event.touches[0].clientX;
  const offsetX = currentX - startX.value;
  progressBar.value = Math.min(100, Math.max(0, _progressBar + offsetX / progress.value.clientWidth * 100));
  currentTime.value = duration.value * progressBar.value / 100
  
}
async function handleTouchEnd() {
  isScale.value = false
  // 可能初次进来直接拖动播放
  source.stop();
  source.disconnect();
  diffTime.value = currentTime.value - source.context.currentTime
  // 继续播放
  source = ctx.createBufferSource() 
  let audioBuffer = await loadAudio()
  duration.value = audioBuffer.duration
  playSound(audioBuffer, currentTime.value)
  // 监听是否播放完成
}

// 播放音频
async function loadAudio(isShowLoading = false) {
  // 设置状态加载中  拖拽进度条不显示
  if (isShowLoading) {
    const toast = showLoadingToast({
      duration: 0,
      forbidClick: true,
      message: '加载中...',
    });
  }
  const audioUrl = musicList.value[musicIndex.value].song_url;
  const res = await fetch(audioUrl);
  const arrayBuffer = await res.arrayBuffer(); // byte array字节数组
  const audioBuffer = await ctx.decodeAudioData(arrayBuffer, function(
    decodeData
  ) {
    return decodeData;
  });
  return audioBuffer;
}
async function playSound(audioBuffer, time = 0) {
  source.buffer = audioBuffer; // 设置数据
  source.connect(ctx.destination); // 头尾相连
  // 可以对音频做任何控制
  source.start(0, time); // 播放方法.立即播放
  closeToast();
  time === 0 && (diffTime.value = -ctx.currentTime)
  updateProgress() // 进度条
  store.setPlayStatus(true)

  // 监听是否播放完成
  source.onended = onPlayEnd
}
async function onPlayEnd() {
  store.setPlayStatus(false)
  // 循环播放
  if (playType.value === 1) {
    let index = musicIndex.value + 1
    if (index >= musicList.value.length) {
      index = 0
    }
    store.setMusicIndex(index)
  }
   // 随机播放
  if (playType.value === 3) {
    store.setMusicIndex(randomNum(musicIndex.value))
  }
  // 单曲循环
  nextTick(async () => {
    await clearAudio()
    initPlayAudio(playType.value === 2 ? false : true)
  })
}
// 清除引用恢复默认值
function clearAudio() {
  currentTime.value = 0
  diffTime.value = 0
  duration.value = 0
  progressBar.value = 0
  window.clearTimeout(timer.value)
  console.log(source, '清除音频·')
  if (source) {
    source.stop();
    source.disconnect();
    source = null
  }
}
// 切换下一曲
function onChangeMusic(direction) {
  // 上一首
  if (direction === -1) {
    let index = musicIndex.value - 1
    if (index < 0) {
      index = musicList.value.length - 1
    }
    store.setMusicIndex(index)
  } else {
    let index = musicIndex.value + 1
    if (index >= musicList.value.length) {
      index = 0
    }
    store.setMusicIndex(index)
  }
  clearAudio()
  nextTick(() => {
    initPlayAudio(true)
  })
}
// 随机播放生成随机数
function randomNum(init) {
  let randomIdx = Math.floor(Math.random() * musicList.value.length)
  if (randomIdx === init) {
    return randomNum(init)
  }
  return randomIdx
}

defineExpose({
  initPlayAudio,
  clearAudio,
  playtOrPauseAudio
});
</script>
<style lang="scss" scoped>


.control_box {
  -touch-callout: none; 
  -webkit-user-select: none;
  background: #161616;
  padding-left: 16px;
  padding-right: 16px;
  box-sizing: content-box;
  padding-bottom: constant(safe-area-inset-bottom);                                                     
  padding-bottom: env(safe-area-inset-bottom);
  border-top: 1px solid rgba(245,210,144,0.1);
  &.fixed {
    position: fixed;
    left: 0;
    right: 0;
    bottom: calc(54px + constant(safe-area-inset-bottom));
    bottom: calc(54px + env(safe-area-inset-bottom));
    background: #2D2D2D;
    padding-bottom: 0;
    border: 0;
  }
  .control {
    height: 60px;
  }
  
  .opt_icon {
    width: 24px;
    height: 24px;
  }
  .opt_center_icon {
    width: 32px;
    height: 32px;
    margin: 0 12px;
  }
}
.progress {
  font-size: 10px;
  color: #ADADAD;
  line-height: 10px;
  margin-left: 16px;
  .progress_bar {
    width: 183px;
    height: 1px;
    background:rgba(255,255,255,0.1);
    position: relative;
    .progress_bar_inner {
      position: absolute;
      left: 0;
      top: 0;
      height: 1px;
      background: #FFFFFF;
      span {
        position: absolute;
        width: 6px;
        height: 6px;
        background: #FFFFFF;
        border-radius:6px;
        right: -3px;
        top: -3px;
        &:after {
          position: absolute;
          left: -6px;
          top: -6px;
          right: -6px;
          bottom: -6px;
        }
        &.scale_circle {
          transform: scale(1.9);
          transition: all .5s;
        }
      }
    }
  }
}


.music_info {
  padding-top: 18px;
  padding-bottom: 10px;
  font-weight: 600;
  font-size: 14px;
  color: #FFFFFF;
  .cover_img {
    width: 40px;
    height: 40px;
    border-radius: 4px;
    margin-right: 8px;
  }
  .music_opt {
    width: 32px;
    height: 32px;
    display: block;
    margin-left: 16px;
  }
}
</style>